﻿// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
// TRANSFORM_TEX(v.uv, _MainTex): v.uv * _MainTex_ST.xy + _MainTex_ST.zw

/*******************************************************
i.normal = UnityObjectToWorldNormal(v.normal); 

i.normal = mul(transpose((float3x3)unity_ObjectToWorld), v.normal);
i.normal = normalize(i.normal);

inline float3 UnityObjectToWorldNormal(in float3 norm) {
	return normalize(
		unity_WorldToObject[0].xyz * norm.x +
		unity_WorldToObject[1].xyz * norm.y +
		unity_WorldToObject[2].xyz * norm.z;
	);
}
*******************************************************/

/*******************************************************
inline half DotClamped(half3 a, half3 b) {
	#if (SHADER_TARGET < 30 || defined(SHADER_API_PS3))
		return saturate(dot(a, b));
	#else
		return max(0.0h, dot(a, b));
	#endif
}
*******************************************************/

/*******************************************************
half SpecularStrength(half3 specular) {
	#if (SHADER_TARGET < 30)
		return specular.r;
	#else
		return max(max(specular.r, specular.g), specular.b);
	#endif
}

inline half3 EnergyConservationBetweenDiffuseAndSpecular(
	half3 albedo, half specColor, out half oneMinusReflectivity
) {
	oneMinusReflectivity = 1 - SpecularStrength(specColor);
	#if !UNITY_CONSERVE_ENERGY
		return albedo;
	#elif UNITY_CONSERVE_ENERGY_MONOCHROME
		return albedo * oneMinusReflectivity;
	#else
		return albedo * (half3(1, 1, 1) - specColor);
	#endif
}
*******************************************************/

/*******************************************************
inline half OneMinusReflectivityFromMetallic(half metallic) {
	half oneMinusDielectricSpec = unity_ColorSpaceDielectricSpec.a;
	return oneMinusDielectricSpec * (1 - metallic);
}
inline half DiffuseAndSpecularFromMetallic(
	half3 albedo, half metallic, out half3 specColor, out half oneMinusReflectivity
) {
	specColor = lerp(unity_ColorSpaceDielectricSpec.rgb, albedo, metallic);
	oneMinusReflectivity = OneMinusReflectivityFromMetallic(metallic);
	return albedo * oneMinusReflectivity;
}
*******************************************************/

Shader "Custom/Project3/LightingShader1"
{
	Properties {
		_Tint ("Tint", Color) = (1, 1, 1, 1)
		_MainTex ("Albedo", 2D) = "white" {}
		[Gamma] _Metallic ("Metallic", Range(0, 1)) = 0
		_Smoothness ("Smoothness", Range(0, 1)) = 0.5
	}
	
	SubShader 
	{
		Pass
		{
			Tags
			{
				"LightMode" = "ForwardBase"
			}
			CGPROGRAM
				
				#pragma vertex MyVertexProgram
				#pragma fragment MyFragmentProgram
				
				#include "UnityStandardBRDF.cginc"
				#include "UnityStandardUtils.cginc"
				
				float4 _Tint;
				sampler2D _MainTex;
				float4 _MainTex_ST;
				float _Metallic;
				float _Smoothness;
				
				struct VertexData {
					float4 position : POSITION;
					float2 uv : TEXCOORD0;
					float3 normal : NORMAL;
				};
				
				struct Interpolators {
					float4 position : POSITION;
					float2 uv : TEXCOORD0;
					float3 normal : TEXCOORD1;
					float3 worldPos : TEXCOORD2;
				};
				
				Interpolators MyVertexProgram(VertexData v) {
					Interpolators i;
					i.position = UnityObjectToClipPos(v.position);
					i.worldPos = mul(unity_ObjectToWorld, v.position);
					i.normal = UnityObjectToWorldNormal(v.normal);
					i.uv = TRANSFORM_TEX(v.uv, _MainTex);
					return i;
				}
				
				float4 MyFragmentProgram(Interpolators i) : SV_TARGET {
					i.normal = normalize(i.normal); // 误差很小，可以不调用，以提升性能
					
					float3 lightDir = _WorldSpaceLightPos0.xyz;
					float3 lightColor = _LightColor0.rgb;
					
					float3 albedo = tex2D(_MainTex, i.uv).rgb * _Tint.rgb;
					float3 specularTint;
					float oneMinusReflectivity;
					albedo *= DiffuseAndSpecularFromMetallic(
						albedo, _Metallic, specularTint, oneMinusReflectivity
					);
					float3 diffuse = albedo * lightColor * DotClamped(lightDir, i.normal);
					
					float3 viewDir = normalize(_WorldSpaceCameraPos - i.worldPos);
					float3 halfVector = normalize(lightDir + viewDir);
					float3 specular = specularTint.rgb * lightColor * pow(
						DotClamped(halfVector, i.normal), _Smoothness * 100
					);
					
					return float4(diffuse + specular, 1);
				}
				
			ENDCG
		}
	}
}















